<template>
  <div class="page-container">
    <el-container>
      <el-aside width="250px" class="page-aside" v-drag v-collapse>
        <div class="page-aside-grow">
          <div class="button-top">
            <el-button
              type="success"
              @click="(event) => { event.currentTarget.blur(); buy(); }"
              :plain="formData.orderType !== 23"
              size="large"
            ><i class="fa fa-sign-in"/>&nbsp;买入</el-button>
            <el-button
              type="danger"
              @click="(event) => { event.currentTarget.blur(); sell(); }"
              :plain="formData.orderType !== 24"
              size="large"
            ><i class="fa fa-sign-out"/>&nbsp;卖出</el-button>
          </div>
          <el-form
            ref="dataForm"
            label-width="80px"
            label-position="right"
            :model="formData"
            :rules="rules"
          >
            <el-row v-if="showBrokerAccount">
              <el-col :span="24">
                <el-form-item label="资金账号" prop="brokerAccountId">
                  <el-select v-model="formData.brokerAccountId">
                    <el-option
                      v-for="item in accountList"
                      :key="item.brokerAccountId"
                      :label="item.account + ' (' + item.brokerName + ')'"
                      :value="item.brokerAccountId"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="24">
                <el-form-item label="证券代码" prop="code">
                  <el-input v-model="formData.code" @input="changeCode" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="24">
                <el-form-item :label="(formData.orderType === 23 ? '买入' : '卖出') + '价格'" prop="price">
                  <cm-number v-model="formData.price" :point="2"></cm-number>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="24">
                <el-form-item :label="(formData.orderType === 23 ? '买入' : '卖出') + '数量'" prop="volume">
                  <cm-number v-model="formData.volume" :point="0"></cm-number>
                </el-form-item>
              </el-col>
            </el-row>
            <div class="max-tips">
              <div @click="fillMaxVolume" v-if="formData.orderType === 23">最多可买入 {{maxVolume}} 股</div>
              <div @click="fillMaxVolume" v-if="formData.orderType === 24">最多可卖出 {{maxVolume}} 股</div>
            </div>
          </el-form>
          <div class="button-bottom">
            <el-button
              size="large"
              type="primary"
              @click="submitForm"
              :loading="editLoading"
            >提交</el-button>
          </div>
          <div class="tick" v-if="tickList && tickList.length > 0">
            <div
              v-for="item in tickList"
              :class="[
                'tick-item',
                item.type === 2 ? 'tick-sell tick-sell-' + item.index : '',
                item.type === 0 ? 'tick-new' : '',
                item.type === 1 ? 'tick-buy tick-buy-' + item.index : '',
              ]"
              @click="clickTick(item)"
            >
              <span class="title">
                <span v-if="item.type === 2">卖</span>
                <span v-if="item.type === 0">最新</span>
                <span v-if="item.type === 1">买</span>
                <span class="index">{{item.index}}</span>
              </span>
              <span class="price">{{item.price}}</span>
              <span class="volume">{{item.volume}}</span>
            </div>
          </div>
        </div>
      </el-aside>
      <el-main class="page-main">
        <el-tabs v-model="activeName" @tab-click="tabsClick" class="tabs-box">
          <el-tab-pane label="持仓信息" name="position">
            <!--表格内容栏-->
            <cm-table
              ref="positionTable"
              pkName="id"
              :filters="positionFilters"
              :filterFields="positionFilterFields"
              :columns="positionColumns"
              :showLoading="false"
              :showSummary="true"
              :summaryMethod="summaryPositionMethod"
              @handleAfterQuery="positionCallback"
              @handleRowClick="handleRowClick"
            ></cm-table>
          </el-tab-pane>
          <el-tab-pane label="成交信息" name="deal">
            <!--表格内容栏-->
            <cm-table
              ref="dealTable"
              pkName="id"
              dataUrl="/stockDeal/queryPage"
              :filters="dealFilters"
              :filterFields="dealFilterFields"
              :columns="dealColumns"
              :autoLoadPage="false"
              :showLoading="false"
              :showSummary="true"
              :summaryMethod="summaryDealMethod"
            ></cm-table>
          </el-tab-pane>
          <el-tab-pane label="委托信息" name="order">
            <!--表格内容栏-->
            <cm-table
              ref="orderTable"
              pkName="id"
              dataUrl="/stockOrder/queryPage"
              :filters="orderFilters"
              :filterFields="orderFilterFields"
              :columns="orderColumns"
              :operators="[{
                type: '1',
                name: '撤单',
                buttonType: 'ajax',
                buttonLevel: '02',
                buttonClass: 'warning',
                buttonIcon: 'fa fa-sign-in',
                selectedMode: '2',
                dataSourUrl: '',
                dataDestUrl: '/order/cancel',
                clickTips: '请确认是否撤单？'
              }]"
              :opMinWidth="80"
              :autoLoadPage="false"
              :showLoading="false"
              :checkRowOpShow="checkOrderRowOpShow"
            ></cm-table>
          </el-tab-pane>
          <!--表格内容栏
          <el-tab-pane label="资金信息" name="money">
            <cm-table
              ref="moneyTable"
              pkName="id"
              dataUrl="/memberBrokerAccount/queryPage"
              :filters="moneyFilters"
              :filterFields="moneyFilterFields"
              :columns="moneyColumns"
              :autoLoadPage="false"
              :showLoading="false"
            ></cm-table>
          </el-tab-pane>
          -->
          <el-tab-pane label="消息提示" name="message">
            <!--表格内容栏-->
            <cm-table
              ref="messageTable"
              pkName="id"
              dataUrl="/stockOrderMessage/queryPage"
              :filters="messageFilters"
              :filterFields="messageFilterFields"
              :columns="messageColumns"
              :autoLoadPage="false"
              :showLoading="false"
            ></cm-table>
          </el-tab-pane>
        </el-tabs>
      </el-main>
    </el-container>
  </div>
</template>

<script setup>
import {ref, nextTick, onMounted, onUnmounted, watch} from 'vue';
import {ElMessage, ElMessageBox} from "element-plus";
import api from '@/http/api'
import {connectWebsocket, sendMessage} from "@/utils/websocket";
import {emitter} from "@/utils/bus";
import date from "@/utils/date";

const lastPrice = ref({});
const positionFilters = ref({
  code: ''
});
// 分页查询条件
const positionFilterFields = ref([
  {prop: "code", label: "证券代码"}
]);
// 分页列表字段
const positionColumns = ref([
  {prop: "code", label: "证券代码", width: 100},
  {prop: "name", label: "证券名称", width: 100},
  {prop: "volume", label: "持仓数量", minWidth: 90, type: 'number', align: 'right'},
  {prop: "price", label: "持仓均价", minWidth: 90, type: 'number', point: 2, align: 'right'},
  {prop: "frozenVolume", label: "冻结数量", minWidth: 90, type: 'number', align: 'right'},
  {prop: "availableVolume", label: "可用数量", minWidth: 90, type: 'number', align: 'right'},
  {prop: "openMoney", label: "开仓金额", minWidth: 90, type: 'number', point: 2, align: 'right'},
  {prop: "lastPrice", label: "最新价", minWidth: 90, sortable: false, align: 'right', formatter: (prop, value, row) => {
      let stockCode = row.code + '.' + row.exchangeCode;
      let data = lastPrice.value[stockCode];
      if (data && data.lastPrice) {
        return data.lastPrice.toFixed(2);
      } else {
        return '';
      }
    }
  },
  {prop: "marketValue", label: "市值", minWidth: 90, sortable: false, align: 'right', formatter: (prop, value, row) => {
      let stockCode = row.code + '.' + row.exchangeCode;
      let data = lastPrice.value[stockCode];
      if (data && data.lastPrice) {
        let value = (row.volume * data.lastPrice).toFixed(2);
        row.marketValue = value;
        return value;
      } else {
        return '';
      }
    }
  },
  {prop: "profit", label: "盈亏", minWidth: 90, sortable: false, align: 'right', formatter: (prop, value, row) => {
      let stockCode = row.code + '.' + row.exchangeCode;
      let data = lastPrice.value[stockCode];
      if (data && data.lastPrice) {
        let value = ((row.volume * data.lastPrice) - (row.openMoney || 0)).toFixed(2);
        row.profit = value;
        return value;
      } else {
        return '';
      }
    }
  },
]);

const dealFilters = ref({
  code: ''
});
const dealFilterFields = ref([
  {prop: "code", label: "证券代码"},
  {prop: "startDate", label: "开始时间", type: 'date'},
  {prop: "endDate", label: "结束时间", type: 'date'},
]);
const dealColumns = ref([
  {prop: "accountId", label: "资金账户", minWidth: 100},
  {prop: "tradedTime", label: "成交时间", minWidth: 150, formatter: (prop, value, row) => {
      return row.tradedTime ? date.simpleDateFormat(row.tradedTime * 1000, 'yyyy-MM-dd HH:mm:ss') : ''
    }
  },
  {prop: "code", label: "证券代码", minWidth: 100},
  {prop: "name", label: "证券名称", minWidth: 100},
  {prop: "orderType", label: "买卖标记", minWidth: 100, type: 'dic-value', dicCode: 'dicOrderType'},
  {prop: "tradedPrice", label: "成交价格", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "tradedVolume", label: "成交数量", minWidth: 100, type: 'number', align: 'right'},
  {prop: "tradedAmount", label: "成交金额", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "commission", label: "手续费", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "profitMoney", label: "平仓盈亏", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "orderSysId", label: "合同编号", minWidth: 100},
]);

const orderFilters = ref({
  code: ''
});
const orderFilterFields = ref([
  {prop: "code", label: "证券代码"},
  {prop: "startDate", label: "开始时间", type: 'date'},
  {prop: "endDate", label: "结束时间", type: 'date'},
]);
const orderColumns = ref([
  {prop: "accountId", label: "资金账户", minWidth: 100},
  {prop: "createTime", label: "委托时间", width: 150},
  {prop: "code", label: "证券代码", minWidth: 100},
  {prop: "name", label: "证券名称", minWidth: 100},
  {prop: "orderType", label: "买卖标记", minWidth: 100, type: 'dic-value', dicCode: 'dicOrderType'},
  {prop: "status", label: "委托状态", minWidth: 100, type: 'dic-value', dicCode: 'dicStockOrderStatus'},
  {prop: "finished", label: "状态", minWidth: 100, formatter: (prop, value) => {
      return value === 1 ? '已成交' : value === 2 ? '废单' : value === 3 ? '已撤消' : '待成交'
    }
  },
  {prop: "volume", label: "委托数量", minWidth: 100, type: 'number', align: 'right'},
  {prop: "tradedVolume", label: "成交数量", minWidth: 100, type: 'number', align: 'right'},
  {prop: "cancelVolume", label: "已撤数量", minWidth: 100, type: 'number', align: 'right'},
  {prop: "price", label: "委托价格", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "tradedPrice", label: "成交均价", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "freezeMoney", label: "冻结金额", minWidth: 100, type: 'number', point: 2, align: 'right'},
  {prop: "freezeCommission", label: "冻结手续费", minWidth: 120, type: 'number', point: 2, align: 'right'},
  {prop: "orderId", label: "订单编号", minWidth: 100},
  {prop: "orderSysId", label: "合同编号", minWidth: 100},
  {prop: "cancelReason", label: "废单原因", minWidth: 100},
]);

const moneyFilters = ref({
  account: ''
});
const moneyFilterFields = ref([
  {prop: "account", label: "资金账号"}
]);
const moneyColumns = ref([
  {prop: "updateTime", label: "更新时间", width: 150},
  {prop: "brokerName", label: "所属券商", width: 100},
  {prop: "account", label: "资金账号", width: 100},
  {prop: "freezeMoney", label: "冻结金额", minWidth: 90, type: 'number', point: 2},
  {prop: "baseMoney", label: "基数金额", minWidth: 90, type: 'number', point: 2},
  {prop: "availableMoney", label: "可用金额", minWidth: 90, type: 'number', point: 2},
  {prop: "profitMoney", label: "盈亏金额", minWidth: 90, type: 'number', point: 2},
  {prop: "totalAssets", label: "总资产", minWidth: 90, type: 'number', point: 2},
  {prop: "marketMoney", label: "总市值", minWidth: 90, type: 'number', point: 2}
]);

const messageFilters = ref({
  message: ''
});
const messageFilterFields = ref([
  {prop: "message", label: "消息内容"}
]);
// 分页列表字段
const messageColumns = ref([
  {prop: "createTime", label: "时间", width: 160},
  {prop: "accountId", label: "资金账号", width: 100},
  {prop: "message", label: "消息内容", minWidth: 100},
]);
// 表单数据验证规则
const rules = ref({
  brokerAccountId: [
    {required: true, message: '请选择资金账号', trigger: ['blur', 'change']},
  ],
  orderType: [
    {required: true, message: '请选择委托类型', trigger: ['blur', 'change']},
  ],
  code: [
    {
      required: true,
      validator(rule, value, callback) {
        if (!value) {
          return callback(new Error('请输入证券代码'))
        } else if (value.length > 3 && !(value.startsWith("00")
            || value.startsWith("30")
            || value.startsWith("60")
            || value.startsWith("68"))) {
          return callback(new Error('证券代码不正确'))
        } else if (value.length !== 6) {
          return callback(new Error('证券代码必须为 6 位数'))
        } else {
          callback()
        }
      },
      trigger: ['blur']
    }
  ],
  price: [
    {
      required: true,
      validator(rule, value, callback) {
        if (!value) {
          return callback(new Error('请输入' + (formData.value.orderType === 23 ? '买入' : '卖出') + '价格'))
        } else {
          callback()
        }
      },
      trigger: ['blur', 'change']
    }
  ],
  volume: [
    {
      required: true,
      validator(rule, value, callback) {
        if (!value) {
          return callback(new Error('请输入' + (formData.value.orderType === 23 ? '买入' : '卖出') + '数量'))
        } else if (value % 100 !== 0) {
          return callback(new Error((formData.value.orderType === 23 ? '买入' : '卖出') + '数量必须是100倍数'))
        } else if (value > maxVolume.value) {
          return callback(new Error('最多只可' + (formData.value.orderType === 23 ? '买入' : '卖出') + maxVolume.value + '股'))
        } else {
          callback()
        }
      },
      trigger: ['blur', 'change']
    }
  ],
});

const activeName = ref('position');
const dataForm = ref();
const formData = ref({
  orderType: '',
  code: '',
  price: '',
  volume: ''
}); // 弹窗表单数据
const accountList = ref([]); // 用户资金账号
const showBrokerAccount = ref(false);
const tickList = ref([]);
const dialogTitle = ref(''); // 新增/编辑/查看弹窗标题
const dialogVisible = ref(false); // 弹窗是否显示
const dialogEdit = ref(true); // 弹窗表单是否可编辑
const editLoading = ref(false); // 弹窗表单提交状态
const dataTable = ref(); // 弹窗表单提交状态

const positionTable = ref();
const posistionList = ref([]);
const dealTable = ref();
const orderTable = ref();
const moneyTable = ref();
const messageTable = ref();
const interval = ref();

const maxVolume = ref(0);

const tabsClick = () => {
  if (interval.value) {
    clearInterval(interval.value);
  }

  nextTick(() => {
    refreshPage();
    restartRefreshPage();
  });
};

const refreshPage = async(tabName = undefined) => {
  tabName = tabName || activeName.value;
  if (activeName.value !== tabName) {
    await nextTick(() => {});
  }

  switch (tabName) {
    case 'position':
      positionTable.value.findPage();
      return;
    case 'deal':
      dealTable.value.findPage();
      return;
    case 'order':
      orderTable.value.findPage();
      return;
    case 'money':
      moneyTable.value.findPage();
      return;
    case 'message':
      messageTable.value.findPage();
      return;
  }
};

const restartRefreshPage = () => {
  if (interval.value) {
    clearInterval(interval.value);
  }
  interval.value = setInterval(refreshPage, 5000)
}

const handleCellOperator = (property, value, row) => {
  formData.value = Object.assign({}, row);
  dialogVisible.value = true;
  dialogEdit.value = false;
  dialogTitle.value = "查看";

  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
};

const handleRowClick = (row) => {
  formData.value.code = row.code || '';
  changeCode();
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
}

const firstRefresh = ref(true);
const positionCallback = (dataList) => {
  posistionList.value = dataList || [];

  if (firstRefresh.value) {
    refreshLastPrice();
    firstRefresh.value = false;
  }
};

const checkOrderRowOpShow = (button, row) => {
  return row.status === '50' || row.status === '55';
};

const buy = (code = undefined) => {
  formData.value.orderType = 23;
  formData.value.code = code || formData.value.code || '';
  if (accountList.value.length === 1) {
    formData.value.brokerAccountId = accountList.value[0].brokerAccountId;
    showBrokerAccount.value = false;
  } else {
    showBrokerAccount.value = true;
  }
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
}

const sell = (code = undefined) => {
  formData.value.orderType = 24;
  formData.value.code = code || formData.value.code || '';
  if (accountList.value.length === 1) {
    formData.value.brokerAccountId = accountList.value[0].brokerAccountId;
    showBrokerAccount.value = false;
  } else {
    showBrokerAccount.value = true;
  }
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
}

const fillMaxVolume = () => {
  formData.value.volume = maxVolume.value;
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
}

const timeoutHandler = ref();

const changeCode = () => {
  if (formData.value.code && formData.value.code.length === 6) {
    sendMessage({type: 'tick', code: formData.value.code});

    if (timeoutHandler.value) {
      clearTimeout(timeoutHandler.value);
    }

    timeoutHandler.value = setTimeout(changeCode, 5000);
  }
}

const calcMaxVolume = () => {
  if (formData.value.orderType === 24) {
    if (posistionList.value) {
      let sellVolume = 0;
      posistionList.value.filter(item => item.code === formData.value.code).forEach(item => {
        sellVolume += item.volume;
      });
      maxVolume.value = sellVolume;
    }

    return;
  }

  // (int (总金额 * 30%/20% - 持仓金额, 有效金额) / (买入价格 * 100)) * 100;
  if (!formData.value.brokerAccountId || !posistionList.value || !formData.value.price) {
    maxVolume.value = 0;
    return;
  }

  let rate = formData.value.code.indexOf('60') === 0 || formData.value.code.indexOf('00') === 0 ? 0.3 :
    (formData.value.code.indexOf('30') === 0 ? 0.2 : 0);
  if (rate === 0) {
    maxVolume.value = 0;
    return;
  }

  let account = accountList.value.find(item => item.brokerAccountId === formData.value.brokerAccountId);
  if (!account) {
    maxVolume.value = 0;
    return;
  }

  let baseMoney = account.baseMoney || 0;
  let availableMoney = account.availableMoney || 0;
  let positionMoney = 0;
  posistionList.value.filter(item => item.code === formData.value.code).forEach(item => {
    positionMoney += item.volume * item.price;
  });
  let buyMoney = (baseMoney - positionMoney) * rate;
  if (buyMoney > availableMoney) {
    buyMoney = availableMoney;
  }
  let buyVolume = Math.trunc(buyMoney / formData.value.price / 100) * 100;
  if (buyVolume > 100) {
    maxVolume.value = buyVolume;
  } else {
    maxVolume.value = 0;
  }
};

const showTick = (data) => {
  let code = data.code.split('.')[0];
  if (code !== formData.value.code) return;

  tickList.value = [];
  let list = [];
  for (let i=data.askPrice.length - 1; i>=0; i--) {
    list.push({
      type: 2,
      index: (i + 1),
      price: data.askPrice[i].toFixed(2),
      volume: data.askVol[i]
    });
  }
  list.push({
    type: 0,
    index: null,
    price: data.lastPrice.toFixed(2),
    volume: (data.lastPrice - data.lastClose).toFixed(2)
  });
  for (let i=0; i<data.bidPrice.length; i++) {
    list.push({
      type: 1,
      index: (i + 1),
      price: data.bidPrice[i].toFixed(2),
      volume: data.bidVol[i]
    });
  }
  tickList.value = list;
};

const showTickList = (data) => {
  if (data) {
    lastPrice.value = data || {};
  }
};

const clickTick = (tick) => {
  formData.value.price = tick.price || '';
  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
};

const showMessage = (data) => {
  let message = data.message || '';
  if (message.indexOf("失败") > 0) {
    ElMessage.error(message);
  } else if (message.indexOf("成功") > 0) {
    ElMessage.success(message);
  } else {
    ElMessage.info(message);
  }
}

// 表单提交
const submitForm = () => {
  dataForm.value && dataForm.value.validate((valid) => {
    if (valid) {
      let tips = '请确认是否[' + (formData.value.orderType === 23 ? '买入' : '卖出') + ']' +
        '[' + formData.value.code + '][' + formData.value.volume + ']股';
      ElMessageBox.confirm(tips, '提示', {type: 'info'}).then(() => {
        editLoading.value = true;
        api.post('/order/order', formData.value).then(res => {
          ElMessage.success(res.message);
          editLoading.value = false;
          refreshPage('order')
        }).catch(() => {
          editLoading.value = false;
        });
      }).catch(()=>{});
    } else {
      ElMessage.error('数据录入不正确，请重新检查！');
    }
  })
};

const summaryPositionMethod = (param) => {
  const { columns, data } = param
  const sums = []
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = '合计'
      return
    } else if (index === 1 || index === 2 || index === 4 || index === 8) {
      sums[index] = ''
      return
    }
    const values = data.map((item) => Number(item[column.property]))
    if (!values.every((value) => Number.isNaN(value))) {
      sums[index] = `${values.reduce((prev, curr) => {
        const value = Number(curr)
        if (!Number.isNaN(value)) {
          return prev + curr
        } else {
          return prev
        }
      }, 0).toFixed(2)}`
    } else {
      sums[index] = '0'
    }
  })

  return sums
};

const summaryDealMethod = (param) => {
  const { columns, data } = param
  const sums = []
  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = '合计'
      return
    } else if (index === 1 || index === 2 || index === 3 || index === 4 || index === 5 || index === 6 || index === 11) {
      sums[index] = ''
      return
    }
    const values = data.map((item) => Number(item[column.property]))
    if (!values.every((value) => Number.isNaN(value))) {
      sums[index] = `${values.reduce((prev, curr) => {
        const value = Number(curr)
        if (!Number.isNaN(value)) {
          return prev + curr
        } else {
          return prev
        }
      }, 0).toFixed(2)}`
    } else {
      sums[index] = '0'
    }
  })

  return sums
};

const loadUserAccount = async() => {
  await api.post('/member/queryBrokerAccountList').then(res => {
    accountList.value = res.data || [];
  });
};

const lastPriceTimeout = ref();
const refreshLastPrice = () => {
  if (activeName.value === 'position' && posistionList.value) {
    let codeList = [];
    posistionList.value.forEach(item => codeList.push(item.code));
    if (codeList.length > 0) {
      sendMessage({type: 'tick_list', code: codeList.join(',')});
    }
  }

  if (lastPriceTimeout.value) {
    clearTimeout(lastPriceTimeout.value);
  }
  lastPriceTimeout.value = setTimeout(refreshLastPrice, 5000);
};

watch(() => formData.value, () => calcMaxVolume(), {deep: true});

onMounted(async() => {
  await loadUserAccount();
  await nextTick(() => restartRefreshPage());
  await nextTick(() => refreshLastPrice());
  buy();

  connectWebsocket();
  emitter.on("tick", (data) => showTick(data));
  emitter.on("tick_list", (data) => showTickList(data));
  emitter.on("message", (data) => showMessage(data));
});

onUnmounted(() => {
  if (interval.value) {
    clearInterval(interval.value);
  }
  if (timeoutHandler.value) {
    clearTimeout(timeoutHandler.value);
  }
  if (lastPriceTimeout.value) {
    clearTimeout(lastPriceTimeout.value);
  }

  emitter.off("tick");
  emitter.off("tick_list");
  emitter.off("message");
});
</script>

<style scoped lang="scss">
.page-aside {
  padding-top: 10px;
  overflow: auto;
  .page-aside-grow {
    padding-right: 2px;
    flex-direction: column;
    .max-tips {
      width: 100%;
      text-align: center;
      cursor: pointer;
      margin-bottom: 10px;
    }
    .button-top {
      width: 100%;
      margin-bottom: 10px;
      display: flex;
      flex-direction: row;
      align-items: start;
    }
    .button-bottom {
      width: 100%;
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
    }
    .tick {
      margin-top: 10px;
      display: flex;
      flex-direction: column;
      border: 1px solid rgb(135, 190, 227);
      .tick-item {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        padding: 5px 10px;
      }
      .tick-item:hover {
        cursor: pointer;
        background: rgb(202, 241, 255);
      }
      .index {
        color: white;
        padding: 0 3px;
        margin-left: 5px;
      }
      .title {
        width: 50px;
      }
      .price {
        color: rgb(12, 169, 0);
        font-weight: 600;
        flex-grow: 1;
        text-align: center;
      }
      .volume {
        min-width: 50px;
        font-weight: 600;
        text-align: right;
      }
      .tick-sell {
        background: rgb(241, 248, 238);
        .index {
          background: rgb(84, 124, 255);
        }
      }
      .tick-buy {
        background: rgb(255, 242, 237);
        .index {
          background: rgb(249, 83, 66);
        }
      }
      .tick-sell-1 {
        background: rgb(205, 232, 197);
      }
      .tick-sell-4 .price, .tick-sell-5 .price {
        color: rgb(249, 83, 66);
      }
      .tick-sell-3 .price {
        color: #000000;
      }
      .tick-buy-1 {
        background: rgb(255, 210, 195);
      }
      .tick-new {
        background: rgb(234, 246, 254);
        color: rgb(12, 169, 0);
      }
    }
  }
}
.tabs-box {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.tabs-box :deep(.el-tabs__content) {
  height: 1px;
  flex-grow: 1;
}
.tabs-box :deep(.el-tab-pane) {
  height: 100%;
}
</style>